import sys
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QPushButton, QLabel, QListWidget, 
                            QMessageBox, QFrame)
from PyQt6.QtCore import QTimer, Qt, QThread
import pyaudio
import wave
import threading
import time
import os
from datetime import datetime

class AudioRecorder:
    def __init__(self):
        self.is_recording = False
        self.frames = []
        self.audio = pyaudio.PyAudio()
        self.stream = None
        self.current_file = None
        self._lock = threading.Lock()
        
    def start_recording(self):
        with self._lock:
            self.frames = []
            self.is_recording = True
            if self.stream is None:
                self.stream = self.audio.open(
                    format=pyaudio.paInt16,
                    channels=1,
                    rate=44100,
                    input=True,
                    frames_per_buffer=1024
                )
        
    def stop_recording(self):
        with self._lock:
            self.is_recording = False
            if self.stream is not None:
                try:
                    self.stream.stop_stream()
                    self.stream.close()
                except Exception as e:
                    print(f"关闭音频流时出错: {e}")
                finally:
                    self.stream = None
            self.save_recording()
        
    def save_recording(self):
        try:
            if not os.path.exists("recordings"):
                os.makedirs("recordings")
                
            if not self.frames:
                return
                
            filename = f"recordings/recording_{datetime.now().strftime('%Y%m%d_%H%M%S')}.wav"
            self.current_file = filename
            
            wf = wave.open(filename, 'wb')
            wf.setnchannels(1)
            wf.setsampwidth(self.audio.get_sample_size(pyaudio.paInt16))
            wf.setframerate(44100)
            wf.writeframes(b''.join(self.frames))
            wf.close()
        except Exception as e:
            print(f"保存录音时出错: {e}")
    
    def __del__(self):
        try:
            if self.stream is not None:
                self.stream.stop_stream()
                self.stream.close()
            if self.audio is not None:
                self.audio.terminate()
        except Exception as e:
            print(f"清理资源时出错: {e}")

class RecordingThread(QThread):
    def __init__(self, recorder):
        super().__init__()
        self.recorder = recorder

    def run(self):
        while self.recorder.is_recording:
            try:
                with self.recorder._lock:
                    if self.recorder.stream and self.recorder.is_recording:
                        data = self.recorder.stream.read(1024, exception_on_overflow=False)
                        self.recorder.frames.append(data)
            except Exception as e:
                print(f"录音时出错: {e}")
                break

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.recorder = AudioRecorder()
        self.recording_thread = None
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_timer)
        self.seconds = 0
        
        self.initUI()
        
    def initUI(self):
        self.setWindowTitle('录音软件')
        self.setFixedSize(400, 600)
        
        # 主窗口部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        layout.setSpacing(10)
        
        # 状态标签
        self.status_label = QLabel('就绪')
        self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.status_label.setStyleSheet('font-size: 20px;')
        layout.addWidget(self.status_label)
        
        # 计时器标签
        self.timer_label = QLabel('00:00')
        self.timer_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.timer_label.setStyleSheet('font-size: 30px;')
        layout.addWidget(self.timer_label)
        
        # 录音按钮
        self.record_button = QPushButton('开始录音')
        self.record_button.setFixedWidth(200)
        self.record_button.setStyleSheet('''
            QPushButton {
                background-color: #4CAF50;
                color: white;
                padding: 10px;
                border: none;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
        ''')
        self.record_button.clicked.connect(self.toggle_recording)
        
        button_layout = QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.record_button)
        button_layout.addStretch()
        layout.addLayout(button_layout)
        
        # 分割线
        line = QFrame()
        line.setFrameShape(QFrame.Shape.HLine)
        line.setFrameShadow(QFrame.Shadow.Sunken)
        layout.addWidget(line)
        
        # 文件列表标题和刷新按钮
        list_header = QHBoxLayout()
        list_title = QLabel('录音文件列表')
        list_title.setStyleSheet('font-size: 16px; font-weight: bold;')
        refresh_button = QPushButton('刷新')
        refresh_button.clicked.connect(self.update_files_list)
        list_header.addWidget(list_title)
        list_header.addStretch()
        list_header.addWidget(refresh_button)
        layout.addLayout(list_header)
        
        # 文件列表
        self.files_list = QListWidget()
        layout.addWidget(self.files_list)
        
        self.update_files_list()
        
    def toggle_recording(self):
        if not self.recorder.is_recording:
            try:
                self.recorder.start_recording()
                self.status_label.setText('录音中...')
                self.record_button.setText('停止录音')
                self.record_button.setStyleSheet('''
                    QPushButton {
                        background-color: #f44336;
                        color: white;
                        padding: 10px;
                        border: none;
                        border-radius: 5px;
                    }
                    QPushButton:hover {
                        background-color: #da190b;
                    }
                ''')
                
                self.recording_thread = RecordingThread(self.recorder)
                self.recording_thread.start()
                
                self.seconds = 0
                self.timer.start(1000)
                
            except Exception as e:
                print(f"开始录音时出错: {e}")
                self.status_label.setText('录音启动失败')
                self.recorder.is_recording = False
        else:
            try:
                self.recorder.stop_recording()
                self.status_label.setText('录音已保存')
                self.record_button.setText('开始录音')
                self.record_button.setStyleSheet('''
                    QPushButton {
                        background-color: #4CAF50;
                        color: white;
                        padding: 10px;
                        border: none;
                        border-radius: 5px;
                    }
                    QPushButton:hover {
                        background-color: #45a049;
                    }
                ''')
                self.timer_label.setText('00:00')
                self.timer.stop()
                
                if self.recording_thread:
                    self.recording_thread.wait()
                
                self.update_files_list()
                
            except Exception as e:
                print(f"停止录音时出错: {e}")
                self.status_label.setText('录音停止失败')
    
    def update_timer(self):
        self.seconds += 1
        minutes = self.seconds // 60
        secs = self.seconds % 60
        self.timer_label.setText(f"{minutes:02d}:{secs:02d}")
    
    def update_files_list(self):
        try:
            self.files_list.clear()
            if os.path.exists("recordings"):
                files = sorted(os.listdir("recordings"), reverse=True)
                for file in files:
                    if file.endswith(".wav"):
                        self.files_list.addItem(file)
        except Exception as e:
            print(f"更新文件列表时出错: {e}")
    
    def closeEvent(self, event):
        reply = QMessageBox.question(self, '确认退出',
                                   '确定要退出录音软件吗？',
                                   QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                                   QMessageBox.StandardButton.No)

        if reply == QMessageBox.StandardButton.Yes:
            try:
                if self.recorder.is_recording:
                    self.recorder.stop_recording()
                
                self.recorder.is_recording = False
                
                if self.recorder.stream is not None:
                    self.recorder.stream.stop_stream()
                    self.recorder.stream.close()
                    self.recorder.stream = None
                
                if self.recorder.audio is not None:
                    self.recorder.audio.terminate()
                    self.recorder.audio = None
                
                if self.recording_thread and self.recording_thread.isRunning():
                    self.recording_thread.wait(500)
                
                event.accept()
            except Exception as e:
                print(f"关闭窗口时出错: {e}")
                event.accept()
        else:
            event.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())